#!/usr/bin/env python
# -*- coding: utf-8 -*-
from package import ddt
import sys
import json
import os
import unittest

from utils.library.request_library import RequestsLibrary
import logging

logger = logging.getLogger('log')

file_name = ''
for item in os.listdir('./'):
    if 'test_data_' in item:
        file_name = os.path.join(os.getcwd(), item)
        logger.debug('file_name:{}'.format(file_name))


def get_response_value(response, path):
    try:
        for p in path.split('.')[1:]:
            if p in response:
                response = response[p]
            else:
                raise KeyError('{}不存在key: {}'.format(response, p))
            return response
    except Exception as e:
        raise KeyError(e)


def get_return_value_from_response(response, step_num, return_value):
    logger.debug('操作步骤序号[{}]: 预期返回参数列表 {}'.format(step_num, return_value))
    k = '_'.join(['step', str(step_num), return_value['type'], return_value['name']])
    for p in return_value['path'].split('.')[1:]:
        if p in response:
            response = response[p]
        else:
            raise KeyError('info:响应异常或者绑定参数的key不存在响应信息中, detail: {}中不包含{}'.format(response, p))
    return {k: response}


@ddt.ddt
class MainTest(unittest.TestCase):
    request = RequestsLibrary
    return_values = {}

    def setUp(self):
        pass

    @ddt.file_data(file_name)
    def test_demo(self, name, id, steps):
        logger.info('开始执行测试用例【{}】,id: {}'.format(name, id))
        for step in steps:
            if step['type'] == 'interface':
                logger.info('开始执行操作步骤： {}'.format(step['name']))
                logger.info('操作步骤 step_info： {}'.format(step['step_info']))
                logger.info('操作步骤 params: {}'.format(step['params']))
                logger.info('操作步骤 return_values: {}'.format(step['return_values']))
                logger.info('操作步骤 expect：{}'.format(step['expect']))
                params = self.get_params(step['params'], 'body')
                self.collect_params(params)
                headers = self.get_params(step['params'], 'headers')
                method = step['step_info']['method']
                url = step['step_info']['url']
                step_num = step['step_num']
                return_values = step['return_values']
                response = self.request().user_request(method=method, url=url, params=params, headers=headers)
                r = response.json()
                logger.info('响应信息：{} {}'.format(response, r))
                if len(return_values):
                    self.collect_return_values(r, step_num, return_values)
                if step['expect']:
                    for expect in step['expect']:
                        if expect['type'] == 'code':
                            logger.debug('比较响应状态码： [实际结果：{}] -- [预期结果: {}]'.format(response.status_code, expect['value']))
                            self.assertEqual(
                                response.status_code,
                                expect['value'],
                                msg='比较响应状态码： [实际结果：{}] -- [预期结果: {}]'.format(response.status_code, expect['value']))
                        elif expect['type'] == 'body':
                            logger.debug('校验响应体参数： {}'.format(expect['name']))
                            logger.debug('校验响应体详情： {}'.format(expect))
                            real_value = get_response_value(r, expect['path'])
                            logger.debug('比较响应体参数： [实际结果：{}] -- [预期结果: {}]'.format(real_value, expect['value']))
                            self.assertEqual(
                                real_value,
                                expect['value'],
                                msg='比较响应体参数： [实际结果：{}] -- [预期结果: {}]'.format(real_value, expect['value']))

    def tearDown(self):
        pass

    @staticmethod
    def get_params(params, params_type):
        param_dict = {}
        for param in params:
            if param['type'] == params_type:
                param_dict.update({
                    param['name']: param['value']
                })
        return param_dict

    def collect_params(self, params):
        for k, v in params.items():
            if v.startswith('$') and self.is_has_key(v.lstrip('$')):
                params[k] = self.return_values[v.lstrip('$')]

    def is_has_key(self, k):
        if k in self.return_values:
            return True
        else:
            return False

    def collect_return_values(self, response, step_num, return_values):
        for return_value in return_values:
            r = get_return_value_from_response(response, step_num, return_value)
            self.return_values.update(r)
